import numpy as np
from scipy.optimize import linear_sum_assignment


def hungarian_match(A, B, p):
    A, B = list(A), list(B)
    n, m = len(A), len(B)

    if n == 0 or m == 0:
        return 0

    cost_matrix = np.full((n, m), 10000.0)

    for i, a in enumerate(A):
        for j, b in enumerate(B):
            if a == b:
                cost_matrix[i, j] = 0.0

    row_ind, col_ind = linear_sum_assignment(cost_matrix)

    match_count = sum(cost_matrix[i, j] <= p for i, j in zip(row_ind, col_ind))
    return match_count


def parse_magento_log(log: str):
    sections = {"New items": set(), "Deleted items": set(), "Updated items": set()}

    current_section = None
    for line in log.split("\n"):
        line = line.strip()
        if not line:
            continue

        if line.startswith("New items:"):
            current_section = "New items"
        elif line.startswith("Deleted items:"):
            current_section = "Deleted items"
        elif line.startswith("Updated items:"):
            current_section = "Updated items"
        elif current_section:
            sections[current_section].add(line)

    return sections


def compute_score(solution_str, ground_truth, p=0.0):
    """
    solution_str: predicted string
    ground_truth: ground truth strings
    p: strictness for matching, should be in [0, 1]

    use mix of precision and recall to avoid the model generating a lot of useless items

    reward is normalized to [0, 1]
    """
    solution_dict = parse_magento_log(solution_str)
    ground_truth_dict = parse_magento_log(ground_truth)
    reward = 0
    len_gt = 0
    len_sol = 0
    acc = 0
    for section in ground_truth_dict:
        score = hungarian_match(ground_truth_dict[section], solution_dict[section], p)
        acc += score
        len_gt += len(ground_truth_dict[section])
        len_sol += len(solution_dict[section])
    precision = acc / len_sol if len_sol > 0 else 0
    recall = acc / len_gt if len_gt > 0 else 0
    reward += 2 * precision * recall / (precision + recall) if precision + recall > 0 else 0
    return float(reward)

if __name__ == '__main__':
    log_text = "New items:\nNone\n\nDeleted items:\n[79] generic '\\ue60b SALES Sales \\ue62f Orders Invoices Shipments Credit Memos Billing Agreements Transactions Braintree Virtual Terminal'\n[94] link '\\ue62f'\n[95] menu '' orientation: vertical\n[282] menu '' orientation: vertical\n[435] link 'Orders'\n[436] link 'Invoices'\n[437] link 'Shipments'\n[438] link 'Credit Memos'\n[439] link 'Billing Agreements'\n[440] link 'Transactions'\n[441] link 'Braintree Virtual Terminal'\n\nUpdated items:\n[1025] gridcell '1' required: False\n[1026] gridcell '1' required: False\n[6] menubar '' orientation: horizontal\n[61] img 'Magento Admin Panel'\n[1251] button 'System Messages: 1'\n[1287] StaticText 'Failed to synchronize data to the Magento Business Intelligence service. '\n[8] link '\\ue604 DASHBOARD'\n[80] heading 'Dashboard'\n[12] link '\\ue60b SALES'\n[16] link '\\ue608 CATALOG'\n[1221] textbox '\\ue60c' required: False\n[51] main ''\n[86] StaticText 'Scope:'\n[148] button 'All Store Views' hasPopup: menu\n[271] button 'Reload Data'\n[272] HeaderAsNonLandmark ''\n[327] StaticText 'Advanced Reporting'\n[328] StaticText \"Gain new insights and take command of your business' performance, using our dynamic product, order, and customer reports tailored to your customer data.\"\n[415] StaticText 'Chart is disabled. To enable the chart, click '\n[623] StaticText 'Revenue'\n[500] StaticText '$0.00'\n[624] StaticText 'Tax'\n[625] StaticText 'Shipping'\n[626] StaticText 'Quantity'\n[514] StaticText '0'\n[20] link '\\ue603 CUSTOMERS'\n[24] link '\\ue609 MARKETING'\n[1120] tablist '' multiselectable: False orientation: horizontal\n[28] link '\\ue602 CONTENT'\n[1122] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Bestsellers' expanded: True selected: True controls: grid_tab_ordered_products_content\n[1124] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Most Viewed Products' expanded: False selected: False controls: ui-id-1\n[32] link '\\ue60a REPORTS'\n[36] link '\\ue60d STORES'\n[40] link '\\ue610 SYSTEM'\n[44] link '\\ue612 FIND PARTNERS & EXTENSIONS'\n[1126] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... New Customers' expanded: False selected: False controls: ui-id-2\n[1288] link 'Retry Synchronization'\n[81] link '\\ue600 admin'\n[83] link '\\ue607'\n[151] link '\\ue633 What is this?'\n[1128] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Customers' expanded: False selected: False controls: ui-id-3\n[274] link 'Go to Advanced Reporting \\ue644'\n[1141] tabpanel 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Bestsellers'\n[416] link 'here'\n[1130] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Bestsellers'\n[1132] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Most Viewed Products'\n[1134] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... New Customers'\n[1136] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Customers'\n[1149] table ''\n[1172] row ''\n[1178] columnheader 'Product' required: False\n[1179] columnheader 'Price' required: False\n[1180] columnheader 'Quantity' required: False\n[1173] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/33/'\n[1181] gridcell 'Sprite Yoga Strap 6 foot' required: False\n[1182] gridcell '$14.00' required: False\n[1183] gridcell '6' required: False\n[1174] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/20/'\n[1184] gridcell 'Quest Lumaflex™ Band' required: False\n[1185] gridcell '$19.00' required: False\n[1186] gridcell '6' required: False\n[1175] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/29/'\n[1187] gridcell 'Sprite Stasis Ball 65 cm' required: False\n[1188] gridcell '$27.00' required: False\n[1189] gridcell '6' required: False\n[1176] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/13/'\n[1177] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/25/'\n[423] StaticText 'Lifetime Sales'\n[1190] gridcell 'Overnight Duffle' required: False\n[426] StaticText '$0.00'\n[428] StaticText 'Average Order'\n[433] StaticText 'Last Orders'\n[1191] gridcell '$45.00' required: False\n[917] table ''\n[955] row ''\n[973] columnheader 'Customer' required: False\n[1192] gridcell '5' required: False\n[974] columnheader 'Items' required: False\n[975] columnheader 'Total' required: False\n[956] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/299/'\n[1193] gridcell 'Sprite Stasis Ball 55 cm' required: False\n[957] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/65/'\n[958] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/125/'\n[959] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/136/'\n[1194] gridcell '$23.00' required: False\n[1195] gridcell '5' required: False\n[976] gridcell 'Sarah Miller' required: False\n[977] gridcell '5' required: False\n[978] gridcell '$0.00' required: False\n[979] gridcell 'Grace Nguyen' required: False\n[980] gridcell '4' required: False\n[981] gridcell '$190.00' required: False\n[982] gridcell 'Matt Baker' required: False\n[983] gridcell '3' required: False\n[960] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/230/'\n[945] StaticText 'Last Search Terms'\n[946] table ''\n[984] gridcell '$151.40' required: False\n[961] row ''\n[991] columnheader 'Search Term' required: False\n[992] columnheader 'Results' required: False\n[985] gridcell 'Lily Potter' required: False\n[993] columnheader 'Uses' required: False\n[962] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/25/'\n[963] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/19/'\n[986] gridcell '4' required: False\n[964] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/1/'\n[965] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/11/'\n[966] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/13/'\n[987] gridcell '$188.20' required: False\n[947] StaticText 'Top Search Terms'\n[948] table ''\n[967] row ''\n[988] gridcell 'Ava Brown' required: False\n[989] gridcell '2' required: False\n[990] gridcell '$83.40' required: False\n[994] gridcell 'tanks' required: False\n[995] gridcell '23' required: False\n[996] gridcell '1' required: False\n[997] gridcell 'nike' required: False\n[1009] columnheader 'Search Term' required: False\n[1010] columnheader 'Results' required: False\n[1011] columnheader 'Uses' required: False\n[998] gridcell '0' required: False\n[968] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/11/'\n[969] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/1/'\n[970] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/13/'\n[999] gridcell '3' required: False\n[971] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/25/'\n[972] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/9/'\n[53] link 'Magento Admin Panel'\n[1000] gridcell 'Joust Bag' required: False\n[1] RootWebArea 'Dashboard / Magento Admin' focused: True\n[918] contentinfo ''\n[923] link '\\ue606'\n[1001] gridcell '10' required: False\n[924] StaticText ' Copyright © 2024 Magento Commerce Inc. All rights reserved.'\n[934] StaticText ' ver. 2.4.6'\n[926] link 'Privacy Policy'\n[1002] gridcell '4' required: False\n[1003] gridcell 'hollister' required: False\n[1004] gridcell '1' required: False\n[1005] gridcell '19' required: False\n[1006] gridcell 'Antonia Racer Tank' required: False\n[1007] gridcell '23' required: False\n[1008] gridcell '2' required: False\n[927] StaticText ' |'\n[928] link ' Account Activity'\n[929] StaticText ' | '\n[1012] gridcell 'hollister' required: False\n[930] link 'Report an Issue'\n[1013] gridcell '1' required: False\n[1014] gridcell '19' required: False\n[1015] gridcell 'Joust Bag' required: False\n[1016] gridcell '10' required: False\n[1017] gridcell '4' required: False\n[1018] gridcell 'Antonia Racer Tank' required: False\n[1019] gridcell '23' required: False\n[1020] gridcell '2' required: False\n[1021] gridcell 'tanks' required: False\n[1022] gridcell '23' required: False\n[1023] gridcell '1' required: False\n[1024] gridcell 'WP10' required: False\n"
    log_text_ = "New items:\ngeneric\n[1288] link 'Retry Synchronization'\n\nDeleted items:\n[72] generic '\\ue60b SALES Sales\n\n[71] generic '\\ue60b SALES Sales\n[71] generic '\\ue60b SALES Sales\n[71] '\\ue60b SALES Sales \\ue62f Orders Shipments Credit Memos Billing Agreements Transactions Braintree Virtual Terminal'\n[94] link '\\ue62f'\n[95] menu '' orientation: vertical\n[282] menu '' orientation: vertical\n[435] link 'Orders'\n[436] link 'Invoices'\n[437] link 'Shipments'\n[438] link 'Credit Memos'\n[439] link 'Billing Agreements'\n[440] link 'Transactions'\n[441] link 'Braintree Virtual Terminal'\n\nUpdated items:\n[1025] gridcell '1' required: False\n[1026] gridcell '1' required: False\n[6] menubar '' orientation: horizontal\n[61] img 'Magento Admin Panel'\n[1251] button 'System Messages: 1'\n[1287] StaticText 'Failed to synchronize data to the Magento Business Intelligence service. '\n[8] link '\\ue604 DASHBOARD'\n[80] heading 'Dashboard'\n[12] link '\\ue60b SALES'\n[16] link '\\ue608 CATALOG'\n[1221] textbox '\\ue60c' required: False\n[51] main ''\n[86] StaticText 'Scope:'\n[148] button 'All Store Views' hasPopup: menu\n[271] button 'Reload Data'\n[272] HeaderAsNonLandmark ''\n[327] StaticText 'Advanced Reporting'\n[328] StaticText \"Gain new insights and take command of your business' performance, using our dynamic product, order, and customer reports tailored to your customer data.\"\n[415] StaticText 'Chart is disabled. To enable the chart, click '\n[623] StaticText 'Revenue'\n[500] StaticText '$0.00'\n[624] StaticText 'Tax'\n[625] StaticText 'Shipping'\n[626] StaticText 'Quantity'\n[514] StaticText '0'\n[20] link '\\ue603 CUSTOMERS'\n[24] link '\\ue609 MARKETING'\n[1120] tablist '' multiselectable: False orientation: horizontal\n[28] link '\\ue602 CONTENT'\n[1122] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Bestsellers' expanded: True selected: True controls: grid_tab_ordered_products_content\n[1124] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Most Viewed Products' expanded: False selected: False controls: ui-id-1\n[32] link '\\ue60a REPORTS'\n[36] link '\\ue60d STORES'\n[40] link '\\ue610 SYSTEM'\n[44] link '\\ue612 FIND PARTNERS & EXTENSIONS'\n[1126] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... New Customers' expanded: False selected: False controls: ui-id-2\n [81] link '\\ue600 admin'\n[83] link '\\ue607'\n[151] link '\\ue633 What is this?'\n[1128] tab 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Customers' expanded: False selected: False controls: ui-id-3\n[274] link 'Go to Advanced Reporting \\ue644'\n[1141] tabpanel 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Bestsellers'\n[416] link 'here'\n[1130] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Bestsellers'\n[1132] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Most Viewed Products'\n[1134] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... New Customers'\n[1136] link 'The information in this tab has been changed. This tab contains invalid data. Please resolve this before saving. Loading... Customers'\n[1149] table ''\n[1172] row ''\n[1178] columnheader 'Product' required: False\n[1179] columnheader 'Price' required: False\n[1180] columnheader 'Quantity' required: False\n[1173] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/33/'\n[1181] gridcell 'Sprite Yoga Strap 6 foot' required: False\n[1182] gridcell '$14.00' required: False\n[1183] gridcell '6' required: False\n[1174] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/20/'\n[1184] gridcell 'Quest Lumaflex™ Band' required: False\n[1185] gridcell '$19.00' required: False\n[1186] gridcell '6' required: False\n[1175] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/29/'\n[1187] gridcell 'Sprite Stasis Ball 65 cm' required: False\n[1188] gridcell '$27.00' required: False\n[1189] gridcell '6' required: False\n[1176] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/13/'\n[1177] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/catalog/product/edit/id/25/'\n[423] StaticText 'Lifetime Sales'\n[1190] gridcell 'Overnight Duffle' required: False\n[426] StaticText '$0.00'\n[428] StaticText 'Average Order'\n[433] StaticText 'Last Orders'\n[1191] gridcell '$45.00' required: False\n[917] table ''\n[955] row ''\n[973] columnheader 'Customer' required: False\n[1192] gridcell '5' required: False\n[974] columnheader 'Items' required: False\n[975] columnheader 'Total' required: False\n[956] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/299/'\n[1193] gridcell 'Sprite Stasis Ball 55 cm' required: False\n[957] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/65/'\n[958] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/125/'\n[959] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/136/'\n[1194] gridcell '$23.00' required: False\n[1195] gridcell '5' required: False\n[976] gridcell 'Sarah Miller' required: False\n[977] gridcell '5' required: False\n[978] gridcell '$0.00' required: False\n[979] gridcell 'Grace Nguyen' required: False\n[980] gridcell '4' required: False\n[981] gridcell '$190.00' required: False\n[982] gridcell 'Matt Baker' required: False\n[983] gridcell '3' required: False\n[960] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/sales/order/view/order_id/230/'\n[945] StaticText 'Last Search Terms'\n[946] table ''\n[984] gridcell '$151.40' required: False\n[961] row ''\n[991] columnheader 'Search Term' required: False\n[992] columnheader 'Results' required: False\n[985] gridcell 'Lily Potter' required: False\n[993] columnheader 'Uses' required: False\n[962] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/25/'\n[963] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/19/'\n[986] gridcell '4' required: False\n[964] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/1/'\n[965] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/11/'\n[966] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/13/'\n[987] gridcell '$188.20' required: False\n[947] StaticText 'Top Search Terms'\n[948] table ''\n[967] row ''\n[988] gridcell 'Ava Brown' required: False\n[989] gridcell '2' required: False\n[990] gridcell '$83.40' required: False\n[994] gridcell 'tanks' required: False\n[995] gridcell '23' required: False\n[996] gridcell '1' required: False\n[997] gridcell 'nike' required: False\n[1009] columnheader 'Search Term' required: False\n[1010] columnheader 'Results' required: False\n[1011] columnheader 'Uses' required: False\n[998] gridcell '0' required: False\n[968] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/11/'\n[969] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/1/'\n[970] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/13/'\n[999] gridcell '3' required: False\n[971] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/25/'\n[972] row 'http://ec2-3-23-128-184.us-east-2.compute.amazonaws.com:7780/admin/search/term/edit/id/9/'\n[53] link 'Magento Admin Panel'\n[1000] gridcell 'Joust Bag' required: False\n[1] RootWebArea 'Dashboard / Magento Admin' focused: True\n[918] contentinfo ''\n[923] link '\\ue606'\n[1001] gridcell '10' required: False\n[924] StaticText ' Copyright © 2024 Magento Commerce Inc. All rights reserved.'\n[934] StaticText ' ver. 2.4.6'\n[926] link 'Privacy Policy'\n[1002] gridcell '4' required: False\n[1003] gridcell 'hollister' required: False\n[1004] gridcell '1' required: False\n[1005] gridcell '19' required: False\n[1006] gridcell 'Antonia Racer Tank' required: False\n[1007] gridcell '23' required: False\n[1008] gridcell '2' required: False\n[927] StaticText ' |'\n[928] link ' Account Activity'\n[929] StaticText ' | '\n[1012] gridcell 'hollister' required: False\n[930] link 'Report an Issue'\n[1013] gridcell '1' required: False\n[1014] gridcell '19' required: False\n[1015] gridcell 'Joust Bag' required: False\n[1016] gridcell '10' required: False\n[1017] gridcell '4' required: False\n[1018] gridcell 'Antonia Racer Tank' required: False\n[1019] gridcell '23' required: False\n[1020] gridcell '2' required: False\n[1021] gridcell 'tanks' required: False\n[1022] gridcell '23' required: False\n[1023] gridcell '1' required: False\n[1024] gridcell 'WP10' required: False\n"
    print(compute_score(log_text, log_text, 0.1))